package state;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import java.util.GregorianCalendar;

/**
 * This is a Logging class that adds additional logging information 
 * when writing out a message.
 * 
 * @author Ian Doerr
 */
public class CustomLogger {
    
    private BufferedWriter output;
    
    /**
     * Creates a logger using the given string as the file name
     * The extension .log gets added
     * 
     * @param name
     * @throws IOException
     */
    public CustomLogger(String name) throws IOException
    {
        File f = new File(name + ".log");
        
        output = new BufferedWriter(new FileWriter(f));
    }
    
    /**
     * Closes the logger so that it can no longer be written to.
     * 
     * @throws IOException
     */
    public void closeLogger() throws IOException
    {
        output.close();
    }
    
    /**
     * Writes out the given message to file, as well as the 
     * Thread name, and the time-stamp.
     * 
     * @param message
     */
    private synchronized void writeMessage(String message)
    {
        try
        {
        	
        	String name = Thread.currentThread().getName();
        	
        	GregorianCalendar cal = new GregorianCalendar();
        	
        	String date = cal.get(Calendar.MONTH) + "/" + cal.get(Calendar.DAY_OF_MONTH) +"/" + cal.get(Calendar.YEAR);
        	
        	String time = cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND) + "." + cal.get(Calendar.MILLISECOND);
        	
        	String prefix = name + ": " + date + " " + time + " - ";
            
            String[] lines = message.split("\n");
            
            boolean firstLine = true;
            for (String l : lines)
            {
                if (firstLine)
                {
                    output.write(prefix);
                    output.write(l);
                    firstLine = false;
                }
                else
                {
                    output.append('\t');
                    output.write(l);
                }
                output.append('\n');
            }
            
            output.flush();
        }
        catch (IOException ex)
        {
            System.err.println("Error writing to log!");
            ex.printStackTrace();
        }
        
    }
    
    /**
     * Logs the given message to file.
     * 
     * @param message
     */
    public void log(String message)
    {
        writeMessage(message);
    }
    
    /**
     * Logs the given message to file as well as its class and method name sources
     * 
     * @param message
     * @param className
     * @param methodName
     */
    public void log(String message, String className, String methodName)
    {
        log(className + "->" + methodName + ": " + message);
    }
    
    /**
     * Writes out the given error message
     * 
     * @param message
     */
    public void error(String message)
    {
        writeMessage("ERROR: " + message);
    }
    
    /**
     * Writes out the exception to file
     * 
     * @param ex
     */
    public void error(Exception ex)
    {
        StringBuffer buffer = new StringBuffer();
        buffer.append("ERROR: ");
        buffer.append(ex.getMessage());
        buffer.append('\n');
        
        StackTraceElement[] arr = ex.getStackTrace();
        
        for (StackTraceElement e : arr)
        {
            buffer.append(e.toString());
            buffer.append('\n');
        }
        
        writeMessage(buffer.toString());
    }
    
    /**
     * Writes out the given error, as well as its exception
     * 
     * @param message
     * @param ex
     */
    public void error(String message, Exception ex)
    {
        StringBuffer buffer = new StringBuffer();
        buffer.append("ERROR: ");
        buffer.append(message);
        buffer.append('\n');
        buffer.append(ex.getMessage());
        buffer.append('\n');
        
        StackTraceElement[] arr = ex.getStackTrace();
        
        for (StackTraceElement e : arr)
        {
            buffer.append(e.toString());
            buffer.append('\n');
        }
        
        writeMessage(buffer.toString());
    }
    
}
